/******************************************************************************
 * * mmi_modem_adaptor_sms_file.c - implementation of mmi-modem adaptor, sms file sub-module
 *
 * *(C) Copyright 2019 Asr International Ltd.
 * * All Rights Reserved
 * ******************************************************************************/
#include "stdio.h"
#include "lv_conf.h"
#include "mmi_modem_adaptor_sms_file.h"
#include "ui_log.h"

#if MMI_MODEM_SMS_STORE_IN_FILE != 0
static MMI_Modem_Sms_Box_t smsbox;

void MMI_Modem_Sms_File_Get_Info_Req(MMI_MODEM_SMS_OF_BOX SmsBox)
{
    printf("##interface## %s\n", __FUNCTION__);
    uint32_t sms_content_size;
    uint16_t i = 0;
    MMI_Modem_Msg_Content_Info_t * node;
    MMI_Modem_Read_Sms_Info_Cnf_t *pReadSmsInfoCnf = (MMI_Modem_Read_Sms_Info_Cnf_t *)Hal_Mem_Alloc(sizeof(MMI_Modem_Read_Sms_Info_Cnf_t));
    Hal_Mem_Set(pReadSmsInfoCnf,0,sizeof(MMI_Modem_Read_Sms_Info_Cnf_t));

    pReadSmsInfoCnf->Result = MMI_MODEM_SMS_SUCCESS;
    sms_content_size = sizeof(MMI_Modem_Msg_Content_Info_t) * smsbox.Index_Cnt;
    pReadSmsInfoCnf->pMsgContentInfo = (MMI_Modem_Msg_Content_Info_t *)Hal_Mem_Alloc(sms_content_size);
    Hal_Mem_Set(pReadSmsInfoCnf->pMsgContentInfo, 0, sms_content_size);

    _LV_LL_READ_BACK(smsbox.Sms_List, node) {
        if(MMI_MODEM_SMS_RECEIVED == SmsBox) {
            pReadSmsInfoCnf->SmsBox = MMI_MODEM_SMS_RECEIVED;
            if((node->ReadSmsType == MMI_MODEM_UNREAD) || (node->ReadSmsType == MMI_MODEM_READ)){
                memcpy(&pReadSmsInfoCnf->pMsgContentInfo[i++], node, sizeof(MMI_Modem_Msg_Content_Info_t));
                pReadSmsInfoCnf->ReadMsgCnt++;
            }
        } else if (MMI_MODEM_SMS_SENT == SmsBox) {
            pReadSmsInfoCnf->SmsBox = MMI_MODEM_SMS_SENT;
            if((node->ReadSmsType == MMI_MODEM_UNSENT)||(node->ReadSmsType == MMI_MODEM_SENT)) {
                memcpy(&pReadSmsInfoCnf->pMsgContentInfo[i++], node, sizeof(MMI_Modem_Msg_Content_Info_t));
                pReadSmsInfoCnf->ReadMsgCnt++;
            }
        } else if (MMI_MODEM_SMS_ALL == SmsBox) {
            pReadSmsInfoCnf->SmsBox = MMI_MODEM_SMS_ALL;
            memcpy(&pReadSmsInfoCnf->pMsgContentInfo[i++], node, sizeof(MMI_Modem_Msg_Content_Info_t));
            pReadSmsInfoCnf->ReadMsgCnt++;
        } else {
            printf("%s wrong smsbox type\n", __FUNCTION__);
            return;
        }
    }

    printf("%s sms cont %d\n", __FUNCTION__, pReadSmsInfoCnf->ReadMsgCnt);
#if USE_LV_WATCH_MODEM_ADAPTOR
    MMI_Modem_Read_Sms_Info_Cnf(pReadSmsInfoCnf);
#else
    extern VOID Phone_Modem_Read_Sms_Info_Cnf_Handler(MMI_Modem_Read_Sms_Info_Cnf_t *pReadSmsInfoCnf);
    Phone_Modem_Read_Sms_Info_Cnf_Handler(pReadSmsInfoCnf);
#endif
}

void MMI_Modem_Sms_File_Get_Detail_Req(MMI_Modem_Read_Sms_Detail_On_Sim_Req_t * pReadSmsReq)
{
    printf("##interface## %s\n", __FUNCTION__);
    MMI_Modem_Read_Sms_Detail_On_Sim_Cnf_t *pReadSmsCnf;
    MMI_Modem_Msg_Content_Info_t * node;
    pReadSmsCnf = (MMI_Modem_Read_Sms_Detail_On_Sim_Cnf_t *)Hal_Mem_Alloc(sizeof(MMI_Modem_Read_Sms_Detail_On_Sim_Cnf_t));
    Hal_Mem_Set(pReadSmsCnf,0,sizeof(MMI_Modem_Read_Sms_Detail_On_Sim_Cnf_t));
    pReadSmsCnf->Result = MMI_MODEM_SMS_SUCCESS;

    _LV_LL_READ_BACK(smsbox.Sms_List, node) {
        if(node->MsgIndex == pReadSmsReq->MsgIndex) {
            lv_fs_file_t boxfile;
            uint32_t read_len;

            lv_fs_res_t res = lv_fs_open(&boxfile, MMI_MODEM_SMS_BOX_FILE, LV_FS_MODE_RD | LV_FS_MODE_APPEND);

            if(res == LV_FS_RES_OK) {
                pReadSmsCnf->Result = MMI_MODEM_SMS_SUCCESS;
                pReadSmsCnf->SimId = node->SimId;
                pReadSmsCnf->MsgIndex = node->MsgIndex;
                pReadSmsCnf->pSmsPdu = Hal_Mem_Alloc(MMI_MODEM_SMS_FILE_PDU_TOTAL_SIZE);
                memset(pReadSmsCnf->pSmsPdu, 0, MMI_MODEM_SMS_FILE_PDU_TOTAL_SIZE);
                lv_fs_seek(&boxfile, MMI_MODEM_SMS_FILE_ITEM_TOTAL_SIZE * node->MsgIndex + sizeof(MMI_Modem_Msg_Content_Info_t));
                lv_fs_read(&boxfile, pReadSmsCnf->pSmsPdu, MMI_MODEM_SMS_FILE_PDU_TOTAL_SIZE, &read_len);
            }

            lv_fs_close(&boxfile);
        }
    }

#if USE_LV_WATCH_MODEM_ADAPTOR
    MMI_Modem_Read_Sms_Detail_On_Sim_Cnf(pReadSmsCnf);
#else
    extern VOID Phone_Modem_Read_Sms_Detail_On_Sim_Cnf_Handler(MMI_Modem_Read_Sms_Detail_On_Sim_Cnf_t *pReadSmsCnf);
    Phone_Modem_Read_Sms_Detail_On_Sim_Cnf_Handler(pReadSmsCnf);
    Hal_Mem_Free(pReadSmsReq);
#endif
}

void MMI_Modem_Sms_File_Set_Read_Req(uint32_t MsgIndex)
{
    MMI_Modem_Msg_Content_Info_t * node;
    lv_fs_file_t boxfile;
    uint32_t len;

    lv_fs_res_t res = lv_fs_open(&boxfile, MMI_MODEM_SMS_BOX_FILE, LV_FS_MODE_RD | LV_FS_MODE_APPEND);
    if(res != LV_FS_RES_OK) return;

    _LV_LL_READ_BACK(smsbox.Sms_List, node) {
        if(node->MsgIndex == MsgIndex) {
            if(node->ReadSmsType == MMI_MODEM_UNREAD) { //read more than one time(first time is for blacklist check)
                node->ReadSmsType = MMI_MODEM_READ;
                lv_fs_seek(&boxfile, MMI_MODEM_SMS_FILE_ITEM_TOTAL_SIZE * node->MsgIndex);
                lv_fs_write(&boxfile, node, sizeof(MMI_Modem_Msg_Content_Info_t), &len);
                break;
            }
        }
    }
    lv_fs_close(&boxfile);
}

static void MMI_Modem_Update_Box_Info(void)
{
    lv_fs_file_t boxfile;
    lv_fs_res_t  res;
    uint8_t * pboxbuff;
    uint32_t filesize = 0, readsize, i;
    MMI_Modem_Msg_Content_Info_t * smsdetail;
    lv_ll_t * plist = &smsbox.Sms_List;

    _lv_ll_init(plist, sizeof(MMI_Modem_Msg_Content_Info_t));
    res = lv_fs_open(&boxfile, MMI_MODEM_SMS_BOX_FILE, LV_FS_MODE_RD);

    if(res != LV_FS_RES_OK) {
        res = lv_fs_open(&boxfile, MMI_MODEM_SMS_BOX_FILE, LV_FS_MODE_WR);
        if(res == LV_FS_RES_OK) {
            lv_fs_close(&boxfile);
        } else {
            printf("%s create smsbox file fail\n", __FUNCTION__);
            return;
        }
    }

    lv_fs_size(&boxfile, &filesize);
    smsbox.Index_Cnt = filesize / MMI_MODEM_SMS_FILE_ITEM_TOTAL_SIZE;
    if(smsbox.Index_Cnt > 0){
        pboxbuff = (uint8_t *)lv_mem_alloc(filesize);
        res = lv_fs_read(&boxfile, pboxbuff, filesize, &readsize);
        if(res == LV_FS_RES_OK) {
            for(i = 0; i < readsize - 1; )
            {
                smsdetail = _lv_ll_ins_tail(plist);
                memcpy(smsdetail, &pboxbuff[i], sizeof(MMI_Modem_Msg_Content_Info_t));
                i += MMI_MODEM_SMS_FILE_ITEM_TOTAL_SIZE;
                printf("smsdetail: %d %d %d\n", smsdetail->MsgIndex, smsdetail->ReadSmsType, smsdetail->SimId);
            }
        }
        lv_mem_free(pboxbuff);
    }
    lv_fs_close(&boxfile);
    UI_Log_Out(UI_SUB_MODULE_MODEM_ADP, UI_LOG_LEVEL_TRACE_3, "%s: sms cont %d\n", __FUNCTION__, smsbox.Index_Cnt);
}

static void MMI_Modem_Sms_File_Delete_From_File(void * node)
{
    lv_fs_file_t boxfile;
    lv_fs_res_t  res;
    uint32_t write_pos, len;
    MMI_Modem_Msg_Content_Info_t * smsdetail = node;

    if(node == NULL) {
        printf("%s fatal error, node is null\n", __FUNCTION__);
        return;
    }

    res = lv_fs_open(&boxfile, MMI_MODEM_SMS_BOX_FILE, LV_FS_MODE_RD | LV_FS_MODE_APPEND);

    if(res != LV_FS_RES_OK) {
        printf("%s open file fail\n", __FUNCTION__);
        return;
    }

    //set Item to invalid
    write_pos = smsdetail->MsgIndex * MMI_MODEM_SMS_FILE_ITEM_TOTAL_SIZE;
    lv_fs_seek(&boxfile, write_pos);
    lv_fs_write(&boxfile, smsdetail, sizeof(MMI_Modem_Msg_Content_Info_t), &len);
    lv_fs_close(&boxfile);
}

void MMI_Modem_Sms_File_Delete_Sms_req(MMI_Modem_Delete_Sms_Req_t * pDeleteSms)
{
    uint16_t i;
    MMI_Modem_Msg_Content_Info_t * node;
    uint32_t * Index = pDeleteSms->pMsgIndex;

    for(i = 0; i < pDeleteSms->DeleteMsgCnt; i++) {
        _LV_LL_READ_BACK(smsbox.Sms_List, node) {
            if((*Index == node->MsgIndex) &&
               (pDeleteSms->SimId == pDeleteSms->SimId)) {
                node->ReadSmsType = MMI_MODEM_INVALID;
                MMI_Modem_Sms_File_Delete_From_File(node);
                break;
            }
        }
        Index++;
    }
}

static MMI_Modem_Msg_Content_Info_t * MMI_Modem_Sms_File_Find_Index(uint32_t * Index)
{
    MMI_Modem_Msg_Content_Info_t * node;

    _LV_LL_READ_BACK(smsbox.Sms_List, node) {
        if(node->ReadSmsType == MMI_MODEM_INVALID) {
            *Index = node->MsgIndex;
            return node;
        }
    }

    node = _lv_ll_ins_tail(&smsbox.Sms_List);
    memset(node, 0, sizeof(MMI_Modem_Msg_Content_Info_t));
    *Index = smsbox.Index_Cnt++;
    UI_Log_Out(UI_SUB_MODULE_MODEM_ADP, UI_LOG_LEVEL_TRACE_3, "%s: sms index %d cont %d\n",
               __FUNCTION__, node->MsgIndex, smsbox.Index_Cnt);
    return node;
}

void MMI_Modem_Sms_File_Send_Sms_Req(const char * Number, const char * pText, MMI_MODEM_SIM_ID SimId)
{
    lv_fs_file_t boxfile;
    lv_fs_res_t  res;
    uint32_t opsize, index;
    MMI_Modem_Msg_Content_Info_t * smsdetail;
    uint16_t textlen, pdulen;
    uint8_t * pdu;

    UI_Log_Out(UI_SUB_MODULE_MODEM_ADP, UI_LOG_LEVEL_TRACE_3, "%s: number %s, text %s, simid %d\n",
               __FUNCTION__, Number, pText, SimId);

    res = lv_fs_open(&boxfile, MMI_MODEM_SMS_BOX_FILE, LV_FS_MODE_RD | LV_FS_MODE_APPEND);

    if(res != LV_FS_RES_OK) {
        printf("%s %d open file fail\n", __FUNCTION__, __LINE__);
        _lv_ll_clear(&smsbox.Sms_List);
        memset((void *)(&smsbox), 0, sizeof(MMI_Modem_Sms_Box_t));
        MMI_Modem_Update_Box_Info();
        lv_fs_open(&boxfile, MMI_MODEM_SMS_BOX_FILE, LV_FS_MODE_RD | LV_FS_MODE_APPEND);
    }

    smsdetail = MMI_Modem_Sms_File_Find_Index(&index);
    smsdetail->MsgIndex = index;
    smsdetail->ReadSmsType = MMI_MODEM_SENT;
    smsdetail->SimId = SimId;

    textlen = (strlen(pText) < MMI_MODEM_SMS_FILE_TEXT_MAX) ? strlen(pText) : MMI_MODEM_SMS_FILE_TEXT_MAX;
    pdulen = MMI_MODEM_SMS_FILE_PDU_TOTAL_SIZE;
    pdu = lv_mem_alloc(pdulen);
    if(pdu) {
        memset(pdu, 0, pdulen);
        memcpy(pdu, &textlen, MMI_MODEM_SMS_FILE_LEN_SIZE);  //set TextLen
        memcpy(pdu + MMI_MODEM_SMS_FILE_LEN_SIZE, Number, strlen(Number)); //set Number

        hal_rtc_t tm;
        char time[MMI_MODEM_SMS_FILE_TIME_MAX] = {};

        memset(&time, 0, MMI_MODEM_SMS_FILE_TIME_MAX);
        Hal_Rtc_Gettime(&tm);
        snprintf(time, MMI_MODEM_SMS_FILE_TIME_MAX, "%.4d-%.2d-%.2d %.2d:%.2d", tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min);

        memcpy(pdu + MMI_MODEM_SMS_FILE_LEN_SIZE + MMI_MODEM_SMS_FILE_NUMBER_MAX, time, MMI_MODEM_SMS_FILE_TIME_MAX); //set time
        memcpy(pdu + MMI_MODEM_SMS_FILE_HEADER_TOTAL_SIZE, pText, strlen(pText)); //set text
    } else {
        lv_fs_close(&boxfile);
        _lv_ll_remove(&smsbox.Sms_List, smsdetail);
        return;
    }

    lv_fs_seek(&boxfile, MMI_MODEM_SMS_FILE_ITEM_TOTAL_SIZE * index);
    //write sms detail info
    res = lv_fs_write(&boxfile, smsdetail, sizeof(MMI_Modem_Msg_Content_Info_t), &opsize);
    if(res != LV_FS_RES_OK) {
        lv_fs_close(&boxfile);
        lv_mem_free(pdu);
        _lv_ll_remove(&smsbox.Sms_List, smsdetail);
        return;
    }

    //write sms pdu
    if(index == smsbox.Index_Cnt - 1) pdulen++; //to avoid seek assert
    res = lv_fs_write(&boxfile, pdu, pdulen, &opsize);
    if(res != LV_FS_RES_OK) {
        lv_fs_close(&boxfile);
        lv_mem_free(pdu);
        _lv_ll_remove(&smsbox.Sms_List, smsdetail);
        return;
    }

    lv_fs_close(&boxfile);

#ifdef BUILD_IN_PC_SIMULATOR
    MMI_Modem_Send_Sms_Cnf_t * pSendSmsCnf =
        (MMI_Modem_Send_Sms_Cnf_t *)Hal_Mem_Alloc(sizeof(MMI_Modem_Send_Sms_Cnf_t));

    pSendSmsCnf->Result = MMI_MODEM_SMS_SUCCESS;
    pSendSmsCnf->SimId = SimId;
    pSendSmsCnf->MsgIndex = smsdetail->MsgIndex;

    extern void Phone_Modem_Send_Sms_Cnf_Handler(MMI_Modem_Send_Sms_Cnf_t *pSendSmsCnf);
    Phone_Modem_Send_Sms_Cnf_Handler(pSendSmsCnf);
#endif
}

void MMI_Modem_Sms_File_New_Sms_Ind(app_adp_new_sms_info_ind_t *sms_info)
{
    lv_fs_file_t boxfile;
    lv_fs_res_t  res;
    uint32_t opsize, index;
    MMI_Modem_Msg_Content_Info_t * smsdetail;
    uint8_t * pdu;
    uint32_t pdulen;
    uint16_t data_len = 0;

    //update smsbox file
    res = lv_fs_open(&boxfile, MMI_MODEM_SMS_BOX_FILE, LV_FS_MODE_RD | LV_FS_MODE_APPEND);

    if(res != LV_FS_RES_OK) {
        _lv_ll_clear(&smsbox.Sms_List);
        memset((void *)(&smsbox), 0, sizeof(MMI_Modem_Sms_Box_t));
        MMI_Modem_Update_Box_Info();
        lv_fs_open(&boxfile, MMI_MODEM_SMS_BOX_FILE, LV_FS_MODE_WR);
    }

    smsdetail = MMI_Modem_Sms_File_Find_Index(&index);
    smsdetail->MsgIndex = index;
    smsdetail->ReadSmsType = MMI_MODEM_UNREAD;
    smsdetail->SimId = (MMI_MODEM_SIM_ID)sms_info->simid;

    pdulen = MMI_MODEM_SMS_FILE_PDU_TOTAL_SIZE;
    pdu = lv_mem_alloc(pdulen);
    if(pdu) {
        memset(pdu, 0, pdulen);
        if(MMI_MODEM_SMS_FILE_TEXT_MAX > sms_info->data_len)
        {
            data_len = sms_info->data_len;

        }
        else
        {
            data_len = MMI_MODEM_SMS_FILE_TEXT_MAX;
        }
        memcpy(pdu, &data_len, MMI_MODEM_SMS_FILE_LEN_SIZE);
        memcpy(pdu + MMI_MODEM_SMS_FILE_LEN_SIZE, sms_info->number, sms_info->number_len);
        memcpy(pdu + MMI_MODEM_SMS_FILE_LEN_SIZE + MMI_MODEM_SMS_FILE_NUMBER_MAX, sms_info->time, sms_info->time_len);
        memcpy(pdu + MMI_MODEM_SMS_FILE_HEADER_TOTAL_SIZE, sms_info->data, data_len);
    } else {
        lv_fs_close(&boxfile);
        _lv_ll_remove(&smsbox.Sms_List, smsdetail);
        return;
    }

    lv_fs_seek(&boxfile, MMI_MODEM_SMS_FILE_ITEM_TOTAL_SIZE * index);
    //write sms detail info
    res = lv_fs_write(&boxfile, smsdetail, sizeof(MMI_Modem_Msg_Content_Info_t), &opsize);
    if(res != LV_FS_RES_OK) {
        lv_fs_close(&boxfile);
        lv_mem_free(pdu);
        _lv_ll_remove(&smsbox.Sms_List, smsdetail);
        return;
    }

    //write sms pdu
    if(index == smsbox.Index_Cnt - 1) pdulen++; //to avoid seek assert
    res = lv_fs_write(&boxfile, pdu, pdulen, &opsize);
    if(res != LV_FS_RES_OK) {
        lv_fs_close(&boxfile);
        lv_mem_free(pdu);
        _lv_ll_remove(&smsbox.Sms_List, smsdetail);
        return;
    }

    lv_mem_free(pdu);
    lv_fs_close(&boxfile);
    MMI_Modem_Report_New_Sms_Ind_t  * pRepNewSms =
        (MMI_Modem_Report_New_Sms_Ind_t *)lv_mem_alloc(sizeof(MMI_Modem_Report_New_Sms_Ind_t));

    memcpy(&pRepNewSms->MsgContentInfo, smsdetail, sizeof(MMI_Modem_Msg_Content_Info_t));

#if USE_LV_WATCH_MODEM_ADAPTOR
    MMI_Modem_Rep_New_Sms_Ind(pRepNewSms);
#else
    extern VOID Phone_Modem_Rep_New_Sms_Ind(MMI_Modem_Report_New_Sms_Ind_t *pRepNewSms);
    Phone_Modem_Rep_New_Sms_Ind(pRepNewSms);
#endif
}

void MMI_Modem_Sms_File_DecodeSmsPdu(char * pPdu, char ** number, char ** time, char ** data)
{
    uint16_t textlen = *(uint16_t *)pPdu;
    pPdu += MMI_MODEM_SMS_FILE_LEN_SIZE;
    *number = Hal_Mem_Alloc(MMI_MODEM_SMS_FILE_NUMBER_MAX);
    memset(*number, 0, MMI_MODEM_SMS_FILE_NUMBER_MAX);
    strncpy(*number, pPdu, MMI_MODEM_SMS_FILE_NUMBER_MAX);
    pPdu += MMI_MODEM_SMS_FILE_NUMBER_MAX;
    *time =  Hal_Mem_Alloc(MMI_MODEM_SMS_FILE_TIME_MAX);
    memset(*time, 0, MMI_MODEM_SMS_FILE_TIME_MAX);
    strncpy(*time, pPdu, MMI_MODEM_SMS_FILE_TIME_MAX);
    pPdu += MMI_MODEM_SMS_FILE_TIME_MAX;
    *data = Hal_Mem_Alloc(textlen + 1);
    memset(*data, 0, textlen + 1);
    strncpy(*data, pPdu, textlen);
}

void MMI_Modem_Sms_File_Init(void)
{
    //read smsbox info
    memset(&smsbox, 0, sizeof(MMI_Modem_Sms_Box_t));
    MMI_Modem_Update_Box_Info();

#if USE_LV_WATCH_MODEM_ADAPTOR
    app_adaptor_new_sms_info_ind_bind(MMI_Modem_Sms_File_New_Sms_Ind, APP_SMS_CODE_TYPE_UTF_8);
#endif
}

#endif
